      $ SET SOURCEFORMAT "FREE"
IDENTIFICATION DIVISION.
PROGRAM-ID.  Transactions.
AUTHOR.  Raj Akula.
* Demonstrates how to read an Indexed file sequentially
* on any of its keys

*Not really using the enviromeent division 
ENVIRONMENT DIVISION.

*Here use this to open each file and i open both
*  customers and inventory file in read mode
*  but i open the transactions in sorted order according
*  to customer number so its easier to write the invoices.
*  Also i create 3 ouptut files to get the report of the
*  materials needed to be ordered, customer invoices,
*  as well as the error report.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
   

   SELECT TransactionFile ASSIGN TO "sortedtransactions.dat"
          ORGANIZATION IS LINE SEQUENTIAL
          ACCESS MODE IS SEQUENTIAL.
 		  
   SELECT CustomerFile ASSIGN TO "idxcustomers.dat"
          ORGANIZATION IS INDEXED   
          ACCESS MODE IS DYNAMIC
          RECORD KEY IS CustNo
          ALTERNATE RECORD KEY IS CustomerName
                      WITH DUPLICATES
          FILE STATUS IS CustStatus.
         
   SELECT InventoryFile ASSIGN TO "IdxInventory.dat"
          ORGANIZATION IS INDEXED   
          ACCESS MODE IS DYNAMIC
          RECORD KEY IS ProductNo
          ALTERNATE RECORD KEY IS ProductDesc
                      WITH DUPLICATES
          FILE STATUS IS InventoryStatus.
		  
   SELECT ReOrderFile ASSIGN TO "ReOrderList.rpt"
          ORGANIZATION IS LINE SEQUENTIAL
          ACCESS MODE IS SEQUENTIAL.

   SELECT InvoiceReportFile ASSIGN TO "InvoiceReport.rpt"
          ORGANIZATION IS LINE SEQUENTIAL
          ACCESS MODE IS SEQUENTIAL.
		  
   SELECT ErrorReportFile ASSIGN TO "ErrorReport.rpt"
          ORGANIZATION IS LINE SEQUENTIAL
          ACCESS MODE IS SEQUENTIAL.


*Here i just define each of the files and how to read or write the record. 
DATA DIVISION.
FILE SECTION.
  
FD TransactionFile.
01 TransactionRecord.
   88 EndOfFile VALUE HIGH-VALUE.
   02 TransCustNo          PIC 9(5).
   02 Filler               PIC X(5).
   02 TransProductNo       PIC X(6).
   02 Filler               PIC X(6).
   02 Quantity             PIC 9.
   02 Filler               PIC X(5).
   02 SaleCode             PIC X(1).
   
FD CustomerFile.
01 CustomerRecord.
   02 CustNo                  PIC 9(5).  
   02 FILLER                  PIC X(5).  
   02 CustomerName            PIC X(23).
   02 CustAddress.
      03 CustStreet           PIC X(23).
      03 CustCity             PIC X(13).
      03 CustStateCountry     PIC X(12).
   02 OutStandingBal          PIC 99999V99.
   
FD InventoryFile.
01 InventoryRecord.
    02 ProductNo			PIC 9(6).
    02 Filler                  PIC X(5).
	02 ProductDesc			PIC X(25).
	02 Stock                   PIC 99.
	02 Filler                  PIC X(5).
	02 MinStock                PIC 99.
	02 Filler                  PIC X(5).
	02 Price                   PIC 9999V99.

FD InvoiceReportFile.
01  PrintLine            PIC X(60). 
01 InvReportCustomerName 		 PIC X(23).
01 InvReportCustStreet           PIC X(23).
01 InvReportCustCity             PIC X(13).
01 InvReportCustStateCountry     PIC X(12).
01 InvReportLineItem.
    02 InvReportItemProductDesc	PIC X(25). 
	02 InvReportItemQuantity    PIC 9.
	02 FILLER					PIC X(3).
	02 InvReportItemAmount  	PIC 999.99.
	02 FILLER					PIC X(2).
	02 InvReportItemTotal	    PIC 999.99.
	02 FILLER					PIC X(3).
	02 InvReportItemSales       PIC 999.99.
01 InvReportItemTotalsLine. 
	02 InvReportTotalText 		PIC X(45).
	02 InvReportItemTotals		PIC 99999.99.
01 InvReportGrandTotalLine.
	02 InvReportGrandTotalText PIC X(45).
	02 InvReportGrandTotal PIC 99999.99.
FD ErrorReportFile.
01 ErrorRecord PIC X(60).

FD ReOrderFile.
01 ReOrderRecord.
	02 ReOrderProduct	PIC X(25).
	02 ReOrderQuantity  PIC 99.
 

*These are all basically records that i need temporarily. 
WORKING-STORAGE SECTION.
01 PrnCustomerRecord.
   02 PrnCustNo                  PIC 9(5).  
   02 FILLER             		 PIC X(5).  
   02 PrnCustomerName            PIC X(23).
   02 PrnCustAddress.
      03 PrnCustStreet           PIC X(23).
      03 PrnCustCity             PIC X(13).
      03 PrnCustStateCountry     PIC X(12).
   02 PrnOutStandingBal          PIC 99999V99.
   
01 PrnInventoryRecord.
	02 PrnProductNo			PIC 9(6).
	02 Filler          		PIC X(5).
	02 PrnProductDesc		PIC X(25).
	02 PrnStock           	PIC 99.
	02 Filler          		PIC X(5).
	02 PrnMinStock       	PIC 99.
	02 Filler            	PIC X(5).
	02 PrnPrice          	PIC 9999V99.

01 ReorderItem.
	02 ReOrderProductDesc 	PIC X(25).
	02 ReOrderQty			PIC 99.
01 QtyShort PIC 99.

01 InvoiceLineItem.
    02 LineItemProductDesc		PIC X(25). 
	02 LineItemQuantity      	PIC 9.
	02 FILLER					PIC X(3).
	02 LineItemAmount  			PIC 9999V99.
	02 FILLER					PIC X(2).
	02 LineItemTotal			PIC 99999V99.
	02 FILLER					PIC X(3).
	02 LineItemSales            PIC 99999V99.

01 InvItemTotalsLine. 
	02 InvTotalText 	PIC X(45).
	02 InvItemTotal		PIC 99999V99.
01 InvoiceGrandTotalLine.
	02 InvGrandTotalText PIC X(45).
	02 InvoiceGrandTotal PIC 99999V99.

01 InvoiceHeader1.
    02 InvCustomerName 			 PIC X(23).
	02 InvCustAddress.
      03 InvCustStreet           PIC X(23).
      03 InvCustCity             PIC X(13).
      03 InvCustStateCountry     PIC X(12).

01 InvoiceHeader2.
    02 InvProductDesc      	PIC X(25) VALUE "Product Description    ".
    02 InvQty               PIC X(3) VALUE "Qty".
	02 FILLER					PIC X(1).
    02 InvPrice             PIC X(5) VALUE "Price".
	02 FILLER				PIC X(3).
    02 InvTotal             PIC X(5) VALUE "Total".
	02 FILLER				PIC X(3).
    02 InvSale              PIC X(9) VALUE "SalePrice".
	
	
01 ErrorCustomerRecord.
	02 ErrCustMsgType 		PIC X(20).
	02 InvalidCustNo  		PIC 9(5).
01 ErrorInvRecord.
	02 ErrInvMsgType 		PIC X(20).
	02 InvalidProductNo  	PIC 9(6).

01 NewCustomerCode			PIC 9(5) VALUE 00000.

   
01   TransactionStatus			PIC X(2).
     88 TransRecordFound        VALUE "00".

01   CustStatus				PIC X(2). 
     88 CustRecordFound     VALUE "00".
     
01	 InventoryStatus			PIC X(2).
      88 InventoryRecordFound   VALUE "00".
	  
	  
	  
PROCEDURE DIVISION.
Begin.

*Opening files
   OPEN INPUT TransactionFile.
   OPEN I-O CustomerFile.
   OPEN I-O InventoryFile.
   OPEN OUTPUT InvoiceReportFile.
   OPEN OUTPUT ErrorReportFile.
   OPEN OUTPUT ReOrderFile.
   
*  The READ..NEXT RECORD will read the file sequentially
*  as if it ordered on whichever key has been 
*  established as the KOR.
   READ TransactionFile NEXT RECORD 
      AT END SET EndOfFile TO TRUE
   END-READ.
*Loop to run through end of file
   PERFORM UNTIL EndOfFile
*Move things temporarily so i can check matches for customer number
* and product key
	  MOVE TransCustNo to CustNo
	  MOVE TransProductNo to ProductNo
*Checking if customer number matches with the records
	  READ CustomerFile
		KEY IS CustNo
		INVALID KEY PERFORM ErrorCostomer
	  END-READ
*If it is found move so i can print and update
	  IF CustRecordFound
*	  DISPLAY "Found Cutomer"
	  MOVE CustomerRecord to PrnCustomerRecord
*	  DISPLAY " Customer record: ", PrnCustomerRecord
*	  DISPLAY "PrnOutStandingBal: ",PrnOutStandingBal
	  END-IF
* Here checkinng the part number and if its correct move and for print
	  READ InventoryFile
		KEY IS ProductNo
		INVALID KEY   PERFORM ErrorInventory
	  END-READ
	  IF InventoryRecordFound
*	  DISPLAY "Found Product"
*	  DISPLAY ProductNo
*	  DISPLAY ProductDesc 
*	  DISPLAY Stock 
*	  DISPLAY MinStock
*	  DISPLAY Price
	  
	  MOVE InventoryRecord to PrnInventoryRecord
*	  DISPLAY PrnInventoryRecord
*	  DISPLAY PrnPrice
*Computations for price and had to do this for alignment
	  COMPUTE PrnPrice = PrnPrice /100

	  END-IF
	  DISPLAY  " "
	  DISPLAY  " "
*Here if both found then i write to invoice
	  If CustRecordFound and InventoryRecordFound THEN
*Here i am checking whether to print new customer or not... 
		IF  TransCustNo is not equal to NewCustomerCode THEN
			If NewCustomerCode not equal to 0 THEN
				PERFORM WriteInvoiceTotals
				ADD InvItemTotal to InvoiceGrandTotal	
*				DISPLAY CustomerRecord
			END-IF
			DISPLAY  " "
			DISPLAY  " "
*			DISPLAY "New Customer"
			PERFORM WriteInVoiceAddress
  			
			MOVE TransCustNo TO  NewCustomerCode
			MOVE 0 TO InvItemTotal
		END-IF
*		DISPLAY  TransactionRecord
		
*		DISPLAY LineItemProductDesc,"  ",LineItemQuantity,"  ",LineItemAmount,"  ",LineItemTotal,"  ",LineItemSales
*Here i check whethter i need to order more pieces and there are two cases one where i don't have enough to cover the required
*  quantity or i have enough but it surpases the needed amount
* 
		MOVE PrnProductDesc to LineItemProductDesc
		IF Quantity GREATER THAN OR EQUAL TO PrnStock
			MOVE PrnStock to LineItemQuantity
			MOVE 0 to PrnStock
			COMPUTE QtyShort = Quantity - PrnStock
			IF PrnMinStock = 10 THEN
				COMPUTE ReOrderQty = 15
			END-IF
			IF PrnMinStock = 8 THEN
				COMPUTE ReOrderQty = 12
			END-IF
			IF PrnMinStock not equal to 10 or PrnMinStock not equal to 8 THEN
				COMPUTE ReOrderQty = 5
			END-IF
		END-IF	
		If  Quantity LESS THAN PrnStock  THEN
		    SUBTRACT Quantity FROM PrnStock GIVING PrnStock
			MOVE Quantity TO LineItemQuantity
			IF PrnStock  LESS THAN OR EQUAL TO PrnMinStock THEN
				IF PrnMinStock = 10 THEN
					COMPUTE ReOrderQty = 15 - PrnStock
				END-IF
				IF PrnMinStock = 8 THEN
					COMPUTE ReOrderQty = 12 - PrnStock
				END-IF
				IF PrnMinStock not equal to 10 or PrnMinStock not equal to 8 THEN
					COMPUTE ReOrderQty = 5 - PrnStock
				END-IF
			END-IF
		END-IF
		IF ReOrderQty > 0 THEN
			MOVE ProductDesc TO ReOrderProductDesc
			WRITE ReOrderRecord FROM ReOrderItem
		END-IF
		DISPLAY "Before PrnStock : ", Stock
		REWRITE InventoryRecord FROM PrnInventoryRecord
* Here i update inventory quantity. 	  
	  READ InventoryFile
		KEY IS ProductNo
		INVALID KEY   PERFORM ErrorInventory
	  END-READ
	  DISPLAY " After PrnStock : ", Stock
		
		MOVE PrnPrice TO  LineItemAmount  
		MOVE zero to LineItemTotal
*        DIVIDE PrnPrice BY 100 GIVING PrnPrice
		MULTIPLY LineItemQuantity BY PrnPrice 
		GIVING LineItemTotal  
		ON SIZE ERROR DISPLAY "MULTIPLY ERROR"
		END-MULTIPLY
		MOVE 0 to LineItemSales
* I calculate the discount
		IF SaleCode = 'A' THEN
		    MOVE LineItemTotal to LineItemSales
			MULTIPLY 0.9 BY LineItemSales
		END-IF
		IF SaleCode = 'B' THEN	
			MULTIPLY 0.8 BY LineItemTotal GIVING LineItemSales
		END-IF
		IF SaleCode = 'C' THEN	
			MULTIPLY 0.75 BY LineItemTotal GIVING LineItemSales
		END-IF
		IF SaleCode = 'D' and Quantity > 2 THEN 
			SUBTRACT PrnPrice FROM LineItemTotal GIVING LineItemSales
		END-IF
		IF SaleCode = 'D' and Quantity LESS THAN  3 THEN
			MOVE LineItemTotal to LineItemSales
		END-IF

		IF SaleCode = 'E' THEN
			COMPUTE LineItemSales = LineItemTotal - (((LineItemQuantity - FUNCTION MOD(LineItemQuantity,2))/2)*PrnPrice)
 		END-IF
		
		IF SaleCode = 'Z' THEN
			MOVE LineItemTotal to LineItemSales
		END-IF
		ADD  LineItemSales to InvItemTotal
		PERFORM UpdateCustomerFile

*		DISPLAY InvoiceLineItem
		PERFORM WriteInvoiceLineItem
*		WRITE PrintLine FROM InvoiceLineItem
*		LineItemProductDesc," ",LineItemQuantity," ",LineItemAmount," ",LineItemTotal," ",LineItemSales
	  END-IF
*Here i go to next record in the loop

      READ TransactionFile NEXT RECORD 
        AT END SET EndOfFile TO TRUE
		ADD InvItemTotal to InvoiceGrandTotal	
		PERFORM WriteEndOfFileTotals
      END-READ
   END-PERFORM.

*Close out the files
   CLOSE CustomerFile.
   CLOSE InventoryFile.
   CLOSE TransactionFile.
   CLOSE InvoiceReportFile.
   CLOSE ErrorReportFile.
   CLOSE ReOrderFile
   STOP RUN.

*Functions to do the writing into files
WriteInVoiceAddress.
	DISPLAY PrnCustomerName
	DISPLAY PrnCustStreet  
	DISPLAY PrnCustCity         
	DISPLAY PrnCustStateCountry 
	DISPLAY "========================================================"
	DISPLAY InvoiceHeader2
	DISPLAY "========================================================"
	DISPLAY " "
 	MOVE SPACES TO PrintLine
	WRITE PrintLine
	WRITE PrintLine
	WRITE PrintLine from PrnCustomerName  
	WRITE PrintLine from PrnCustStreet 
	WRITE PrintLine from PrnCustCity 
	WRITE PrintLine from PrnCustStateCountry
	MOVE "========================================================" TO PrintLine
	WRITE PrintLine
	WRITE PrintLine FROM InvoiceHeader2
	MOVE "========================================================" TO PrintLine
	WRITE PrintLine
	MOVE SPACES TO PrintLine
	WRITE PrintLine.

WriteInvoiceTotals.
	MOVE SPACES TO PrintLine
	WRITE PrintLine.
 	MOVE  InvItemTotal TO InvReportItemTotals
	DISPLAY "========================================================" 
	DISPLAY "                                     Total   ", InvReportItemTotals
	DISPLAY "========================================================" 
	MOVE "========================================================" TO PrintLine
	WRITE PrintLine
	MOVE "                                     Total   " TO InvReportTotalText
 	MOVE  InvItemTotal TO InvReportItemTotals
	WRITE PrintLine FROM InvReportItemTotalsLine
	MOVE "========================================================" TO PrintLine
	WRITE PrintLine.


WriteEndOfFileTotals.
    DISPLAY " "
    PERFORM WriteInvoiceTotals
	MOVE InvoiceGrandTotal to InvReportGrandTotal
	DISPLAY "                       Invoice Grand Total   ", InvReportGrandTotal
	DISPLAY "========================================================"
	MOVE "                            Grand    Total   " TO InvReportGrandTotalText
	WRITE PrintLine FROM InvReportGrandTotalLine
	MOVE "========================================================" TO PrintLine
	WRITE PrintLine.

WriteInvoiceLineItem.
	MOVE LineItemProductDesc TO InvReportItemProductDesc
	MOVE LineItemQuantity TO  InvReportItemQuantity  
	MOVE LineItemAmount TO  InvReportItemAmount  
	MOVE LineItemTotal TO   InvReportItemTotal 
	MOVE LineItemSales TO InvReportItemSales 
	WRITE PrintLine FROM InvReportLineItem
	DISPLAY InvReportLineItem.
	
ErrorCostomer.
	DISPLAY "INVALID Customer KEY ", CustNo 
	MOVE "Invalid Customer Record Key " to ErrCustMsgType
	MOVE CustNo to InvalidCustNo
	WRITE ErrorRecord FROM ErrorCustomerRecord.
	
ErrorInventory.
	DISPLAY "INVALID Product KEY " , ProductNo
	MOVE "Invalid Inventory Record Key " to ErrInvMsgType
	MOVE ProductNo to InvalidProductNo
	WRITE ErrorRecord FROM ErrorInvRecord.
	
UpdateCustomerFile.
*	DISPLAY "Before : ", PrnOutStandingBal
*	DISPLAY "LineItemSales: ", LineItemSales
	ADD LineItemSales to  PrnOutStandingBal 
*	COMPUTE PrnOutStandingBal = PrnOutStandingBal 
*    DISPLAY "After : ", PrnOutStandingBal 
	MOVE PrnCustomerRecord to CustomerRecord
	REWRITE CustomerRecord. 